@use '@angular/cdk';
@use '../core/tokens/m2/mat/menu' as tokens-mat-menu;
@use '../core/tokens/token-utils';
@use '../core/style/menu-common';
@use '../core/style/button-common';
@use '../core/style/vendor-prefixes';

// Prevent rendering mat-menu as it can affect the flex layout.
mat-menu {
  display: none;
}

.mat-mdc-menu-content {
  margin: 0;
  padding: 8px 0;
  outline: 0;

  &,
  .mat-mdc-menu-item .mat-mdc-menu-item-text {
    @include vendor-prefixes.smooth-font();
    flex: 1;
    white-space: normal;

    @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
      @include token-utils.create-token-slot(font-family, item-label-text-font);
      @include token-utils.create-token-slot(line-height, item-label-text-line-height);
      @include token-utils.create-token-slot(font-size, item-label-text-size);
      @include token-utils.create-token-slot(letter-spacing, item-label-text-tracking);
      @include token-utils.create-token-slot(font-weight, item-label-text-weight);
    }
  }
}

@keyframes _mat-menu-enter {
  from {
    opacity: 0;
    transform: scale(0.8);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes _mat-menu-exit {
  from {
    opacity: 1;
  }

  to {
    opacity: 0;
  }
}

.mat-mdc-menu-panel {
  @include menu-common.base;
  box-sizing: border-box;
  outline: 0;
  animation: _mat-menu-enter 120ms cubic-bezier(0, 0, 0.2, 1);

  @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
    @include token-utils.create-token-slot(border-radius, container-shape);
    @include token-utils.create-token-slot(background-color, container-color);
    @include token-utils.create-token-slot(box-shadow, container-elevation-shadow);
  }

  // TODO(crisbeto): we don't need this for anything, but it was there when
  // we used MDC's structural styles and removing it leads to sub-pixels
  // differences in text rendering which break a lot of screenshots internally.
  // We should clean it up eventually and re-approve all the screenshots.
  will-change: transform, opacity;

  &.mat-menu-panel-exit-animation {
    animation: _mat-menu-exit 100ms 25ms linear forwards;
  }

  &.mat-menu-panel-animations-disabled {
    animation: none;
  }

  // Prevent users from interacting with the panel while it's animating. Note that
  // people won't be able to click through it, because the overlay pane will catch the click.
  // This fixes the following issues:
  //  * Users accidentally opening sub-menus when the `overlapTrigger` option is enabled.
  //  * Users accidentally tapping on content inside the sub-menu on touch devices, if the
  //    sub-menu overlaps the trigger. The issue is due to touch devices emulating the
  //    `mouseenter` event by dispatching it on tap.
  &.mat-menu-panel-animating {
    pointer-events: none;

    // If the same menu is assigned to multiple triggers and the user moves quickly between them
    // (e.g. in a nested menu), the panel for the old menu may show up as empty while it's
    // animating away. Hide such cases since they can look off to users.
    &:has(.mat-mdc-menu-content:empty) {
      display: none;
    }
  }

  @include cdk.high-contrast {
    outline: solid 1px;
  }

  .mat-divider {
    // Use margin instead of padding since divider uses border-top to render out the line.
    @include token-utils.use-tokens(
      tokens-mat-menu.$prefix,
      tokens-mat-menu.get-token-slots()
    ) {
      color: token-utils.get-token-variable(divider-color);
      margin-bottom: token-utils.get-token-variable(divider-bottom-spacing);
      margin-top: token-utils.get-token-variable(divider-top-spacing);
    }
  }
}

.mat-mdc-menu-item {
  display: flex;
  position: relative;
  align-items: center;
  justify-content: flex-start;
  overflow: hidden;
  padding: 0;

  // MDC's menu items are `<li>` nodes which don't need resets, however ours
  // can be anything, including buttons, so we need to do the reset ourselves.
  cursor: pointer;
  width: 100%;
  text-align: left;
  box-sizing: border-box;
  color: inherit;
  font-size: inherit;
  background: none;
  text-decoration: none;
  margin: 0; // Resolves an issue where buttons have an extra 2px margin on Safari.
  min-height: 48px;

  @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
    @include token-utils.create-token-slot(padding-left, item-leading-spacing);
    @include token-utils.create-token-slot(padding-right, item-trailing-spacing);
  }

  @include button-common.reset;

  @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
    $icons-selector: '.material-icons, mat-icon, [matButtonIcon]';

    [dir='rtl'] & {
      @include token-utils.create-token-slot(padding-left, item-trailing-spacing);
      @include token-utils.create-token-slot(padding-right, item-leading-spacing);
    }

    &:has(#{$icons-selector}) {
      @include token-utils.create-token-slot(padding-left, item-with-icon-leading-spacing);
      @include token-utils.create-token-slot(padding-right, item-with-icon-trailing-spacing);
    }

    [dir='rtl'] &:has(#{$icons-selector}) {
      @include token-utils.create-token-slot(padding-left, item-with-icon-trailing-spacing);
      @include token-utils.create-token-slot(padding-right, item-with-icon-leading-spacing);
    }
  }

  @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
    // The class selector isn't specific enough to overide the link pseudo selectors so we need
    // to target them specifically, otherwise the item color might be overwritten by the user
    // agent resets of the app.
    &, &:visited, &:link {
      @include token-utils.create-token-slot(color, item-label-text-color);
    }

    .mat-icon-no-color,
    .mat-mdc-menu-submenu-icon {
      @include token-utils.create-token-slot(color, item-icon-color);
    }
  }

  &[disabled] {
    cursor: default;
    opacity: 0.38;

    // The browser prevents clicks on disabled buttons from propagating which prevents the menu
    // from closing, but clicks on child nodes still propagate which is inconsistent (see #16694).
    // In order to keep the behavior consistent and prevent the menu from closing, we add an overlay
    // on top of the content that will catch all the clicks while disabled.
    &::after {
      display: block;
      position: absolute;
      content: '';
      top: 0;
      left: 0;
      bottom: 0;
      right: 0;
    }
  }

  // Inherited from MDC and necessary for some internal tests.
  &:focus {
    outline: 0;
  }

  .mat-icon {
    flex-shrink: 0;
    @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
      margin-right: token-utils.get-token-variable(item-spacing);
      height: token-utils.get-token-variable(item-icon-size);
      width: token-utils.get-token-variable(item-icon-size);
    }
  }

  [dir='rtl'] & {
    text-align: right;

    .mat-icon {
      margin-right: 0;
      @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
        margin-left: token-utils.get-token-variable(item-spacing);
      }
    }
  }

  &:not([disabled]) {
    @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
      &:hover {
        @include token-utils.create-token-slot(background-color, item-hover-state-layer-color);
      }

      &.cdk-program-focused,
      &.cdk-keyboard-focused,
      &.mat-mdc-menu-item-highlighted {
        @include token-utils.create-token-slot(background-color, item-focus-state-layer-color);
      }
    }
  }

  @include cdk.high-contrast {
    $outline-width: 1px;

    // We need to move the item 1px down, because Firefox seems to have
    // an issue rendering the top part of the outline (see #21524).
    margin-top: $outline-width;
  }
}

.mat-mdc-menu-submenu-icon {
  @include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
    @include menu-common.item-submenu-icon(
      token-utils.get-token-variable(item-spacing),
      token-utils.get-token-variable(item-icon-size)
    );
  }
}

// Increase specificity because ripple styles are part of the `mat-core` mixin and can
// potentially overwrite the absolute position of the container.
.mat-mdc-menu-item .mat-mdc-menu-ripple {
  @include menu-common.item-ripple;
}
